package org.litespring.beans.factory.support;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.litespring.beans.BeanDefinition;
import org.litespring.beans.factory.BeanCreationException;
import org.litespring.beans.factory.BeanDefinitionStoreException;
import org.litespring.beans.factory.BeanFactory;
import org.litespring.util.ClassUtils;

import java.io.InputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 *
 * Created by brss on 2018/6/9.
 */
public class DefaultBeanFactory implements BeanFactory {

    public static final String ID_ATTRIBUTE = "id";

    public static final String CLASS_ATTRIBUTE = "class";
    /**
     * 用来存放 beanId 和 BeanDefiniton 的映射关系
     */
    private final Map<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();

    /**
     * 构造函数
     * @param configFile 配置文件的位置
     */
    public DefaultBeanFactory(String configFile) {
        //在构造对象时，读取xml文件，把映射关系装入到成员：beanDefinitionMap中
        loadBeanDefinition(configFile);
    }

    /**
     * 读取xml文件中定义的所有的bean，并把读出来的内容装入到new的BeanDefinition对象中。
     * @param configFile
     */
    private void loadBeanDefinition(String configFile) {
        InputStream is = null;
        try{
            ClassLoader cl = ClassUtils.getDefaultClassLoader();
            is = cl.getResourceAsStream(configFile);
            SAXReader reader = new SAXReader();
            Document doc = reader.read(is);
            //root 标签是 <bean>
            Element root = doc.getRootElement();
            Iterator<Element> iter = root.elementIterator();
            while ( iter.hasNext() ){
                Element ele = (Element)iter.next();
                String id = ele.attributeValue(ID_ATTRIBUTE);
                String beanClassName = ele.attributeValue(CLASS_ATTRIBUTE);
                BeanDefinition bd = new GenericBeanDefinition(id,beanClassName);
                this.beanDefinitionMap.put(id,bd);
            }
        }catch (DocumentException e){
            throw new BeanDefinitionStoreException("IOException parsing XML document does't exists.",new Throwable("不知道写啥"));
        }
    }

    public BeanDefinition getBeanDefinition(String beanID) {

        return this.beanDefinitionMap.get(beanID);
    }

    /**
     * 根据beanId反射出这个bean对象
     * @param beanId
     * @return
     */
    public Object getBean(String beanId) {
        BeanDefinition bd = this.getBeanDefinition(beanId);
        if ( bd == null ){
            throw new BeanCreationException("Bean Definition does not exist");
        }
        ClassLoader cl = ClassUtils.getDefaultClassLoader();
        String beanClassName = bd.getBeanClassName();
        try{
            Class<?> clz = cl.loadClass(beanClassName);
            return clz.newInstance();
        }catch (Exception e){
            throw new BeanCreationException("create bean for "+ beanClassName + "failed!");
        }
    }
}